﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
using PingTest.Dto;
using System.Xml.Linq;
using System.Threading;
using PingTest.Service.Interfaces;

namespace PingTestWpfApplication
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Dictionary<string, Timer> timerThreads = null;
        private ISitePingTest pingTestService = null;

        public MainWindow()
        {
            InitializeComponent();
            pingTestService = PingTest.StructureMapConfig.Configuration.GetInstance<ISitePingTest>();
        }

        private void ResetData()
        {
            XDocument xmlDoc = XDocument.Load("Sites.xml");
            var list = (from c in xmlDoc.Descendants("Site")
                        select c.Attribute("Colour")).ToList();
            list.ForEach(x => x.SetValue("#eee"));
            xmlDoc.Save("Sites.xml");
            XmlSource.Refresh();
        }

        private void CreateNewThread(object input)
        {
            lock (this)
            {
                XElement x = (XElement)input;
                var siteInfo = new SiteInfo()
                {
                    SiteUrl = x.Attribute("Url").Value               
                };
                Console.WriteLine(siteInfo.SiteUrl);
                //var colour = "#fff";
                var colour = pingTestService.PingSite(siteInfo);
                XDocument xmlDoc = XDocument.Load("Sites.xml");
                var element = (from y in xmlDoc.Descendants("Site")
                               where y.Attribute("Url").Value == siteInfo.SiteUrl
                               select y).SingleOrDefault();
                element.Attribute("Colour").SetValue(colour);
                xmlDoc.Save("Sites.xml");
                XmlSource.Refresh();
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {            
            AddNew dialog = new AddNew();
            dialog.ShowDialog();
            if (dialog.Url.Text.Length != 0 && dialog.PingRate.Text.Length != 0)
            {
                var xmldoc = XDocument.Load("Sites.xml");
                XElement site = new XElement("Site", new XAttribute("Url", dialog.Url.Text), new XAttribute("PingRate", dialog.PingRate.Text), new XAttribute("Colour", "#fff"));
                xmldoc.Element("Root").Add(site);
                xmldoc.Save("Sites.xml");
                if (CheckTimersExist())
                {
                    timerThreads.Add(site.Attribute("Url").Value, new Timer(CreateNewThread, site, 1000, Convert.ToInt32(Math.Round(Convert.ToDecimal(site.Attribute("PingRate").Value) * 60 * 1000, 0))));
                }
                XmlSource.Refresh();
            }
        }

        private bool CheckTimersExist()
        {
            return timerThreads != null && timerThreads.Count != 0;
        }

        private void Remove_Click(object sender, RoutedEventArgs e)
        {
            var value = ((TextBlock)((Canvas)((Button)sender).Parent).Children[0]).Text;
            var xmldoc = XDocument.Load("Sites.xml");
            (from x in xmldoc.Descendants("Site")
             where x.Attribute("Url").Value == value
             select x).SingleOrDefault().Remove();
            xmldoc.Save("Sites.xml");
            if (timerThreads.Count != 0 && timerThreads != null)
            {
                timerThreads[value].Dispose();
                timerThreads.Remove(value);
            }
            XmlSource.Refresh();
        }

        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            StopThreads();
            base.OnClosing(e);
        }

        private void StopThreads()
        {
            if (timerThreads != null)
            {
                while (timerThreads.Count > 0)
                {
                    var first = timerThreads.First();
                    Console.WriteLine("Stopping:" + first.Key);
                    first.Value.Dispose();
                    timerThreads.Remove(first.Key);                    
                }
            }
        }

        private void Start_Click(object sender, RoutedEventArgs e)
        {
            StatusMessage.Content = "Pings Started";
            timerThreads = new Dictionary<string, Timer>();            
            XDocument xmlDoc = XDocument.Load("Sites.xml");
            xmlDoc.Descendants("Site").ToList()
                .ForEach(x => timerThreads.Add(x.Attribute("Url").Value, new Timer(CreateNewThread, x, 1000, Convert.ToInt32(Math.Round(Convert.ToDecimal(x.Attribute("PingRate").Value) * 60 * 1000, 0)))));
            XmlSource.Refresh();

            Start.Visibility = System.Windows.Visibility.Collapsed;
            Stop.Visibility = System.Windows.Visibility.Visible;            
        }

        private void Stop_Click(object sender, RoutedEventArgs e)
        {
            StatusMessage.Content = "Stopping Threads...";
            StopThreads();
            Stop.Visibility = System.Windows.Visibility.Collapsed;
            Start.Visibility = System.Windows.Visibility.Visible;
            StatusMessage.Content = "Pings Stopped";
        }

        private void Refresh_Click(object sender, RoutedEventArgs e)
        {
            ResetData();
        }

        private void DoubleClickToEdit(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount == 2)
            {
                var value = ((TextBlock)((Canvas)((Border)sender).Child).Children[0]).Text;
                var xmldoc = XDocument.Load("Sites.xml");
                var selected = (from x in xmldoc.Descendants("Site")
                                where x.Attribute("Url").Value == value
                                select x).SingleOrDefault();

                AddNew dialog = new AddNew();
                dialog.Url.Text = selected.Attribute("Url").Value;
                dialog.PingRate.Text = selected.Attribute("PingRate").Value;
                xmldoc.Save("Sites.xml");
                dialog.ShowDialog();
                selected.Attribute("Url").SetValue(dialog.Url.Text);
                selected.Attribute("PingRate").SetValue(dialog.PingRate.Text);
                selected.ReplaceWith(selected);
                xmldoc.Save("Sites.xml");
                if (timerThreads.Count !=0 && timerThreads != null)
                {
                    timerThreads[value].Dispose();
                    timerThreads.Remove(value);
                    timerThreads.Add(dialog.Url.Text, new Timer(CreateNewThread, selected, 1000, Convert.ToInt32(Math.Round(Convert.ToDecimal(selected.Attribute("PingRate").Value) * 60 * 1000, 0))));
                }
                XmlSource.Refresh();
            }
        }
    }
}

